<template>
    <div class="forbid-select">
        <!--    @contextmenu.prevent>-->
        <el-dialog title="Cron" v-model="showDialog" width="745px" :close-on-click-modal="false"
            :append-to-body="true" :modal-append-to-body="true" class="e-page" @open="openCronDialog"
            @close="closeCronDialog" :close-on-press-escape="false">
            <div style="width: 100%" class="cronSelect">
                <div style="display: flex;gap:10px">
                    <!-- 年 -->
                    <div class="cron-item">
                        <el-scrollbar style="height: 100%;width: 100%;">
                            <ul class="el-dropdown-menu el-popper" style="width: 100%">
                                <li class="el-dropdown-menu__item cron-item-info"
                                    @click="click(item.value, index, 'year')" v-for="(item, index) in yearSelect"
                                    ref="year" :value="item.value">
                                    <calendar class="el-icon cron-icon" /><span>{{ item.label }}</span>
                                </li>
                            </ul>
                        </el-scrollbar>
                    </div>
                    <!-- 月 -->
                    <div class="cron-item">
                        <el-scrollbar style="height: 100%;width: 100%;">
                            <ul class="el-dropdown-menu el-popper" style="width: 100%;height: 100%">
                                <li class="el-dropdown-menu__item cron-item-info"
                                    @click="click(item.value, index, 'month')" v-for="(item, index) in monthSelect"
                                    ref="month" :value="item.value">
                                    <calendar class="el-icon cron-icon" /><span>{{ item.label }}</span>
                                </li>
                            </ul>
                        </el-scrollbar>
                    </div>

                    <!-- 日 -->
                    <div class="cron-item">
                        <el-scrollbar style="height: 100%;width: 100%;"
                            :style="{ 'overflow-y': forbidDay ? 'hidden' : 'auto' }">
                            <ul class="el-dropdown-menu el-popper" style="width: 100%;height: 100%">
                                <li class="el-dropdown-menu__item cron-item-info"
                                    @click="click(item.value, index, 'day')" v-for="(item, index) in daySelect"
                                    ref="day" :value="item.value">
                                    <calendar class="el-icon cron-icon" /><span>{{ item.label }}</span>
                                </li>
                            </ul>
                            <div class="placeholder disableSelect" v-if="forbidDay" />
                        </el-scrollbar>
                    </div>

                    <!-- 周 -->
                    <div class="cron-item">
                        <el-scrollbar style="height: 100%;width: 100%;"
                            :style="{ 'overflow-y': forbidWeek ? 'hidden' : 'auto' }">
                            <ul class="el-dropdown-menu el-popper" style="width: 100%;height: 100%">
                                <li class="el-dropdown-menu__item cron-item-info"
                                    @click="click(item.value, index, 'week')" v-for="(item, index) in weekSelect"
                                    ref="week" :value="item.value">
                                    <calendar class="el-icon cron-icon" /><span>{{ item.label }}</span>
                                </li>
                            </ul>
                            <div class="placeholder disableSelect" v-if="forbidWeek" />
                        </el-scrollbar>
                    </div>

                    <!-- 时 -->
                    <div class="cron-item">
                        <el-scrollbar style="height: 100%;width: 100%;">
                            <ul class="el-dropdown-menu el-popper" style="width: 100%;height: 100%">
                                <li class="el-dropdown-menu__item cron-item-info"
                                    @click="click(item.value, index, 'hour')" v-for="(item, index) in hourSelect"
                                    ref="hour" :value="item.value">
                                    <calendar class="el-icon cron-icon" /><span>{{ item.label }}</span>
                                </li>
                            </ul>
                        </el-scrollbar>
                    </div>

                    <!-- 分 -->
                    <div class="cron-item">
                        <el-scrollbar style="height: 100%;width: 100%;">
                            <ul class="el-dropdown-menu el-popper" style="width: 100%;height: 100%">
                                <li class="el-dropdown-menu__item cron-item-info"
                                    @click="click(item.value, index, 'minute')" v-for="(item, index) in minuteSelect"
                                    ref="minute" :value="item.value">
                                    <calendar class="el-icon cron-icon" /><span>{{ item.label }}</span>
                                </li>
                            </ul>
                        </el-scrollbar>
                    </div>

                    <!-- 秒 -->
                    <div class="cron-item">
                        <el-scrollbar style="height: 100%;width: 100%;">
                            <ul class="el-dropdown-menu el-popper" style="width: 100%;height: 100%">
                                <li class="el-dropdown-menu__item cron-item-info"
                                    @click="click(item.value, index, 'second')" v-for="(item, index) in secondSelect"
                                    ref="second" :value="item.value">
                                    <calendar class="el-icon cron-icon" /><span>{{ item.label }}</span>
                                </li>
                            </ul>
                        </el-scrollbar>
                    </div>
                </div>
                <div style="display: flex;gap:10px;margin-top: 10px;">
                    <tooltip v-model="labelCron" class="input-auto-resize" border/>
                    <el-button :icon="getIcon('search')" class="button-auto-resize" :disabled="!labelCron"
                        @click="getNextRunTime" circle />
                    <el-button :icon="getIcon('refresh')" circle class="button-auto-resize" @click="resetCron" />
                    <el-button :icon="getIcon('check')" circle class="button-auto-resize" @click="commitCron"
                        :disabled="disableCommit" />
                </div>
            </div>
        </el-dialog>
        <el-drawer title="NextRunTime" v-model="nextRunTimeDialog" size="400px"
            class="e-page cron-run-time forbid-select" append-to-body :show-close="false">
            <div v-for="(item, index) in nextRunTime" :key="index" class="cron-next-run-time">
                {{ (index + 1) + ' > ' + item }}
            </div>
        </el-drawer>
    </div>
</template>

<script setup>
import { ArrayRemove, checkNull, deepCopy, getIcon } from "@/utils/tools"
import { useElMessage, useModalSize, useRequest } from "@usehook"

const showDialog = defineModel({
    type: Boolean,
    default: false
})

const props = defineProps({
    value: "",
})

const emits = defineEmits(["update:value"])

let cron = $ref({ year: [-1], month: [-1], day: [-1], week: [-1], hour: [], minute: [], second: [0] })
let defaultCron = { year: [-1], month: [-1], day: [-1], week: [-1], hour: [], minute: [], second: [0] }
let backupCron = $ref({})
let nextRunTime = $ref([])
let disableCommit = $ref(true)
let nextRunTimeDialog = $ref(false)

const calendar = getIcon("calendar")

const openCronDialog = () => {
    useModalSize()
}

const closeCronDialog = () => {
    useModalSize(false)
    showDialog.value = false
}

const labelCron = $computed(() => {
    return getCronLabel()
})

const yearSelect = $computed(() => {
    let r = [{ value: -1, label: '每年' }]
    for (let i = 0; i < 10; i++) {
        r.push({ value: 2018 + i, label: 2018 + i + '年' })
    }
    return r
})

const monthSelect = $computed(() => {
    let r = [{ value: -1, label: '每月' }]
    for (let i = 1; i < 13; i++) {
        r.push({ value: i, label: i + "月" })
    }
    return r
})

const weekSelect = $computed(() => {
    let weekMap = { 1: '星期天', 2: '星期一', 3: '星期二', 4: '星期三', 5: '星期四', 6: '星期五', 7: '星期六', }
    let r = [{ value: -1, label: '每星期' }]
    for (let i = 1; i < 8; i++) {
        r.push({ value: i, label: weekMap[i] })
    }
    return r
})

const daySelect = $computed(() => {
    let r = [{ value: -1, label: '每天' }]
    for (let i = 1; i < 32; i++) {
        r.push({ value: i, label: i + '日' })
    }
    return r
})

const hourSelect = $computed(() => {
    let r = [{ value: -1, label: '每小时' }]
    for (let i = 0; i < 24; i++) {
        r.push({ value: i, label: i + '点' })
    }
    return r
})

const minuteSelect = $computed(() => {
    let r = [{ value: -1, label: '每分钟' }]
    for (let i = 0; i < 60; i++) {
        r.push({ value: i, label: i + '分' })
    }
    return r
})

const secondSelect = $computed(() => {
    let r = [{ value: -1, label: '每秒' }]
    for (let i = 0; i < 60; i++) {
        r.push({ value: i, label: i + '秒' })
    }
    return r
})

const forbidWeek = $computed(() => {
    return ((cron.day.length !== 1 && cron.day.length !== 0) || (cron.day.length === 1 && cron.day[0] !== -1))
})

const forbidDay = $computed(() => {
    return ((cron.week.length !== 1 && cron.week.length !== 0) || (cron.week.length === 1 && cron.week[0] !== -1))
})

const isContinuityNum = (num) => {
    let array = []
    if (num instanceof Array) {
        array = [...num]
    } else {
        array = num.toString().split(",")
    }
    if (array.length <= 1) {
        return false
    }
    array = array.map(e => {
        return parseInt(e)
    }).sort()

    let i = array[0]
    let isContinuation = true
    for (let e in array) {
        if (array[e] !== i) {
            isContinuation = false
            break
        }
        i++
    }
    return isContinuation
}

const mergeEle = (ele) => {
    if (isContinuityNum(ele)) {
        let array = []
        if (ele instanceof Array) {
            array = [...ele]
        } else {
            array = ele.split(",")
        }
        return Math.min(...array).toString() + "-" + Math.max(...array).toString()
    }
    return ele
}

const { proxy } = getCurrentInstance()

const click = (val, index, type) => {
    nextRunTime = []
    disableCommit = true
    let _forbidWeek = type === 'week' && val !== -1 && forbidWeek
    let _forbidDay = type === 'day' && val !== -1 && forbidDay
    if (_forbidDay || _forbidWeek) {
        useElMessage.error("day和week不能同时选择")
        return
    }
    let label = proxy.$refs[type][index]
    if (label.style.backgroundColor) {
        label.style.backgroundColor = ''
        ArrayRemove(val, cron[type])
    } else {
        label.style.backgroundColor = '#c1e0ff'
        cron[type].push(val)
    }
    if (index === 0) {
        let loopIndex = 0
        proxy.$refs[type].forEach((label) => {
            if (loopIndex === 0) {
                label.style.backgroundColor = '#c1e0ff'
            } else {
                label.style.backgroundColor = ''
            }
            loopIndex++
        })
        cron[type] = [-1]
    } else {
        proxy.$refs[type][0].style.backgroundColor = ''
        ArrayRemove(-1, cron[type])
    }
}

const getCronLabel = () => {
    let finLabel = []
    for (let i in cron) {
        let ms = cron[i]
        if (ms.length === 1) {
            finLabel.push(ms[0] === -1 ? '*' : ms[0])
        } else {
            finLabel.push(ms.join(','))
        }
    }
    let second = finLabel[6]
    let minute = finLabel[5]
    let hour = finLabel[4]
    let day = finLabel[2]
    let month = finLabel[1]
    let week = finLabel[3]
    let year = finLabel[0]
    if (week !== '*' && day === '*') {
        day = '?'
    } else if (week === '*') {
        week = '?'
    }

    if (checkNull(second) || checkNull(minute) || checkNull(hour) || checkNull(day) || checkNull(month || checkNull(week))) {
        return null
    }
    return mergeEle(second) + ' ' + mergeEle(minute) + ' ' + mergeEle(hour) + ' ' + mergeEle(day) + ' ' + mergeEle(month) + ' ' + mergeEle(week) + (checkNull(year) ? "" : ' ' + mergeEle(year))
}

const fillCronLabel = () => {
    nextTick(() => {
        let initLabel = Object.keys(cron)
        initLabel.forEach(c => {
            proxy.$refs[c].forEach((label) => {
                cron[c].forEach((cron) => {
                    if (label.value === cron) {
                        label.style.backgroundColor = '#c1e0ff'
                    }
                })
            })
        })
    })
}

const clearCronLabel = () => {
    let initLabel = Object.keys(cron)
    nextTick(() => {
        initLabel.forEach(c => {
            proxy.$refs[c].forEach((label) => {
                label.style.backgroundColor = ''
            })
        })
    })
}

const resetCron = () => {
    cron = deepCopy(defaultCron)
    clearCronLabel()
    fillCronLabel()
    disableCommit = true
}

const commitCron = () => {
    if (labelCron) {
        emits("update:value", labelCron)
        showDialog.value = false
    }
}

const transfer = (val) => {
    if (val === '*' || val === '?') {
        return [-1]
    } else if (val.indexOf('-') > 0) {
        let range = val.split('-')
        let rangeFrom = parseInt(range[0])
        let rangeTo = parseInt(range[1])
        return Array.from({ length: rangeTo - rangeFrom + 1 }, (_, index) => index + rangeFrom)
    } else {
        let cron = val.split(',')
        for (let i in cron) {
            cron[i] = parseInt(cron[i])
        }
        return cron
    }
}

const transToCronArray = (val) => {
    let newCron = val.split(' ')
    if (newCron.length === 7) {
        let second = transfer(newCron[0])
        let minute = transfer(newCron[1])
        let hour = transfer(newCron[2])
        let day = transfer(newCron[3])
        let month = transfer(newCron[4])
        let week = transfer(newCron[5])
        let year = transfer(newCron[6])
        return { year, month, day, week, hour, minute, second }
    } else {
        return ""
    }
}

const getNextRunTime = () => {
    useRequest({ url: '/jobinfo/nextTriggerTime', scheduleType: "CRON", scheduleConf: labelCron, size: 20 }).then((resData) => {
        if (resData && resData.status) {
            nextRunTime = resData.data
            disableCommit = false
            nextRunTimeDialog = true
        }
    })
}

watchEffect(() => {
    const value = props.value
    if (showDialog.value) {
        disableCommit = true
        nextRunTime = []
        const tempCron = transToCronArray(value)
        if (value && tempCron) {
            cron = tempCron
            backupCron = tempCron
        } else {
            cron = deepCopy(defaultCron)
        }
        clearCronLabel()
        fillCronLabel()
    }
})
</script>

<style scoped>
:deep(.el-scrollbar) {
    overflow-y: auto;
}

:deep(.el-dropdown-menu) {
    box-shadow: none;
    border: 0;
    margin: 0;
}

:deep(.cronSelect .el-col + .el-col) {
    margin-left: 10px;
}

:deep(.e-page .el-col) {
    margin: 30px 10px 30px 15px
}

:deep(.el-dropdown-menu) {
    padding: 0 !important;
}

:deep(.el-dropdown-menu__item) {
    padding: 0 5px;
}

:deep(.el-button--small.is-circle) {
    margin-top: 5px;
}

:deep(.run-time-row .el-col + .el-col) {
    margin-left: 0;
}

:deep(.disableSelect) {
    background: #e1e4eb63;
    position: absolute;
    height: 500%;
    width: 100%;
    top: 0;
    left: 0;
    z-index: 999;
}

:deep(.cron-item) {
    height: calc((24px + (var(--font-size) - 16px)* 1.5) * 8);
    width: calc(100% / 7);
    border: 1px solid rgb(169 169 169 / 52%);
    border-radius: 4px;
    overflow: hidden;
}

:deep(.cron-item .el-popper) {
    position: relative;
}

:deep(.cron-item-info) {
    font-size: var(--font-size);
    background: rgb(237, 237, 237);
    line-height: calc(var(--font-size) * 1.5);
}

:deep(.cron-item-info:hover) {
    background: rgba(175, 175, 175, .3);
}

.cron-next-run-time {
    font-size: var(--font-size);
    text-align: center;
    width: 80%;
}

.cron-next-run-time+.cron-next-run-time {
    padding-top: 20px;
}

:deep(.cron-icon) {
    padding: 0 5px;
}
</style>

<style>
.cron-run-time .el-drawer__title {
    font-size: calc(var(--font-size) * 1.5);
}

.cron-run-time .el-drawer__header {
    margin-bottom: 0;
    padding: 20px
}

.cron-item .el-scrollbar__bar.is-horizontal,
.cron-item .el-scrollbar__bar.is-vertical {
    display: none !important;
}

.cron-item .el-popper {
    border: 0 !important;
}
</style>
